home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
linuxcon.000
/
linuxcon
/
linuxconf-1.6
/
dnsconf
/
resolv.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-29
|
8KB
|
348 lines
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include "dnsconf.h"
#include "internal.h"
#include "../dialog/dialog.h"
#include "../xconf/xconf.h"
#include "../userconf/userconf.h"
#include "../paths.h"
#include "dnsconf.m"
static DNSCONF_HELP_FILE help_resolv ("resolv");
static DNSCONF_HELP_FILE help_host_conf ("host.conf");
static CONFIG_FILE f_resolv (ETC_RESOLV_CONF,help_resolv
,CONFIGF_MANAGED|CONFIGF_OPTIONNAL);
static CONFIG_FILE f_host_conf (ETC_HOST_CONF,help_host_conf
,CONFIGF_MANAGED|CONFIGF_OPTIONNAL);
PRIVATE void RESOLV::parse (const char *pt)
{
int nb = 0;
while (*pt != '\0'){
pt = str_skip(pt);
char word[200];
pt = str_copyword(word,pt);
if (word[0] == '\0') break;
if (nb == MAX_SEARCH_RESOLV){
xconf_error (MSG_U(E_TOOMSEARCH
,"Too many entries in search statement\n"
"in file %s")
,ETC_RESOLV_CONF);
break;
}
search[nb++].setfrom (word);
}
}
PUBLIC RESOLV::RESOLV()
{
FILE *fin = f_resolv.fopen("r");
if (fin != NULL){
char buf[300];
int noline = 0;
int nbservers = 0;
while (fgets(buf,sizeof(buf),fin)!= NULL){
char key[100];
char *pt = str_copyword(key,str_skip(buf));
noline++;
/* #Specification: netconf / resolv.conf / comment
netconf do not preserve, nor show, comments in
/etc/resolv.conf. I am not even sure if they
are allowed.
*/
if (key[0] != '\0' && key[0] != '#'){
pt = str_skip(pt);
int err = 1;
if (*pt != '\0'){
err = 0;
str_strip (pt,pt);
if (strcmp(key,"domain")==0){
domain.setfrom (pt);
}else if (strcmp(key,"search")==0){
parse (pt);
}else if (strcmp(key,"nameserver")==0){
servers[nbservers++].setfrom(pt);
}else{
err = 1;
}
}
if (err){
xconf_error (MSG_U(E_IVLDLINE,"Invalid line %d in %s")
,noline,ETC_RESOLV_CONF);
}
}
}
fclose (fin);
}
}
PUBLIC int RESOLV::write ()
{
int ret = -1;
FILE *fout = f_resolv.fopen ("w");
if (fout != NULL){
if (!domain.is_empty()) fprintf (fout,"domain %s\n"
,domain.get());
const char *ctl = "search %s";
const char *endctl = "";
for (int i=0; i<MAX_SEARCH_RESOLV; i++){
if (!search[i].is_empty()){
fprintf (fout,ctl,search[i].get());
ctl = " %s";
endctl = "\n";
}
}
fputs (endctl,fout);
for (i=0; i<3; i++){
if (servers[i].is_valid()){
fprintf (fout,"nameserver %s\n"
,servers[i].get());
}
}
ret = fclose (fout);
}
return ret;
}
static const char DNSCONF[]="DNSCONF";
static const char DNSNEEDED[]="dnsneeded";
void dnsconf_editresolv()
{
RESOLV res;
DIALOG dia;
char dnsneeded = (char)linuxconf_getvalnum (DNSCONF,DNSNEEDED,1);
dia.newf_chk (MSG_U(F_DNSNEEDED,"DNS usage"),dnsneeded
,MSG_U(M_DNSNEEDED,"DNS is required for normal operation"));
dia.newf_str (MSG_U(F_DEFDOM,"default domain"),res.domain);
dia.newf_str (MSG_U(F_NAMESERV1,"nameserver 1"),res.servers[0]);
dia.newf_str (MSG_U(F_NAMESERV2,"nameserver 2 (opt)"),res.servers[1]);
dia.newf_str (MSG_U(F_NAMESERV3,"nameserver 3 (opt)"),res.servers[2]);
for (int i=0; i<MAX_SEARCH_RESOLV; i++){
char buf[100];
sprintf (buf,MSG_U(F_SEARCHDOM,"search domain %d (opt)"),i+1);
dia.newf_str (buf,res.search[i]);
}
int nofield = 0;
while (1){
if (dia.edit (
MSG_U(T_RESOLVCONF,"Resolver configuration")
,MSG_U(I_RESOLVCONF
,"You can specify which name server will be used\n"
"to resolv host ip number. Using the DNS is\n"
"to handle this on a TCP/IP network. The others\n"
"are the local /etc/hosts file\n"
" (see \"information about other hosts\" menu\n"
"or the NIS system\n")
,help_resolv.getpath()
,nofield) != MENU_ACCEPT){
break;
}else{
/* We must validate the input somehow */
SSTRING error;
for (int n=0; n<3; n++){
IP_ADDR *s = res.servers + n;
if (!s->is_empty()
&& !s->is_valid()){
char msg[100];
sprintf (msg,MSG_U(E_IVLDIP
,"Invalid IP number for nameserver %d\n"),n+1);
error.append (msg);
}
}
if (error.is_empty()){
if (res.write() != -1){
linuxconf_replace (DNSCONF,DNSNEEDED,dnsneeded);
linuxconf_save();
break;
}
}else{
xconf_error (error.get());
}
}
}
}
/*
Return != 0 if there is at least one nameserver specified in
/etc/resolv.conf (IsReSoLv Configured).
The resolver will use 127.0.0.1 if there is no nameserver entry, but
some routine of linuxconf may assume that if there is no explicit
nameserver, then this machine does not have one running either.
This function also check if the DNS is really needed for normal
operation of the computer. It will return 0 if the DNS is not needed.
*/
int dnsconf_isrslconf()
{
int ret = 0;
if (linuxconf_getvalnum (DNSCONF,DNSNEEDED,1)){
RESOLV res;
for (unsigned i=0; i<sizeof(res.servers)/sizeof(res.servers[0]); i++){
if (!res.servers[i].is_empty()){
ret = 1;
break;
}
}
}
return ret;
}
// Do not translate
static const char *tborder[]={
"hosts, nis, bind",
"hosts, nis",
"hosts, bind, nis",
"hosts, bind",
"hosts",
"nis, hosts, bind",
"nis, hosts",
"nis, bind, hosts",
"nis, bind",
"nis",
"bind, hosts, nis",
"bind, hosts",
"bind, nis, hosts",
"bind, nis",
"bind",
NULL,
};
/*
Do a string compare but compare only visible char (> ' ')
*/
static int dnsconf_strcmp(const char *str1, const char *str2)
{
int ret = -1;
while (1){
str1 = str_skip(str1);
str2 = str_skip(str2);
if (*str1 == *str2){
if (*str1 == '\0'){
ret = 0;
break;
}else{
str1++;
str2++;
}
}else{
ret = *str1 - *str2;
break;
}
}
return ret;
}
/*
Read /etc/host.conf
*/
static void dnsconf_readhostconf (
char &multi, // Tell if the "multi" statement was seen
char &order) // Will contain an index into tborder[]
{
FILE *fin = f_host_conf.fopen ("r");
multi = 0;
order = 0;
if (fin != NULL){
char buf[300];
int noline = 0;
while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
noline++;
char key[300];
char *pt = str_copyword (key,buf);
if (strcmp(key,"multi")==0){
multi = 1;
}else if (strcmp(key,"order")==0){
for (int i=0; tborder[i] != NULL; i++){
if (dnsconf_strcmp(tborder[i],pt)==0){
order = i;
break;
}
}
}else{
xconf_error (MSG_U(E_IVLDKEYW
,"Invalid keyword %s\n"
"in file %s, line %d")
,key,f_host_conf.getpath()
,noline);
}
}
fclose (fin);
}
}
/*
Write /etc/host.conf
*/
static void dnsconf_writehostconf (
char multi, // Tell if the "multi" statement was seen
char order) // Will contain an index into tborder[]
{
FILE *fout = f_host_conf.fopen ("w");
if (fout != NULL){
fprintf (fout,"order %s\n",tborder[order]);
if (multi) fputs ("multi on\n",fout);
fclose (fout);
}
}
/*
Edit the file /etc/host.conf
*/
void dnsconf_editorder()
{
char multi;
char order;
dnsconf_readhostconf(multi,order);
DIALOG dia;
dia.newf_chk ("",multi,MSG_U(F_MULTI,"Multiple IPs for one host"));
dia.newf_title ("","");
// User friendy version of tborder. It must have the same
// order, line by line. "bind" just mean nothing to most people.
static const char *tborder_v[]={
"hosts, NIS, dns",
"hosts, NIS",
"hosts, dns, NIS",
"hosts, dns",
"hosts",
"NIS, hosts, dns",
"NIS, hosts",
"NIS, dns, hosts",
"NIS, dns",
"NIS",
"dns, hosts, NIS",
"dns, hosts",
"dns, NIS, hosts",
"dns, NIS",
"dns",
NULL
};
for (int i=0; tborder_v[i] != NULL; i++){
dia.newf_radio ("",order,i,tborder_v[i]);
}
while (1){
if (dia.edit (MSG_U(T_NAMESERV,"Name service access")
,MSG_U(I_NAMESERV
,"You must tell the system in which order\n"
"the various name services must be probed\n"
"\n"
"hosts mean /etc/hosts is probed\n"
"NIS stand for Network Information System\n"
"dns stands for Domain Name Service\n")
,help_host_conf.getpath()
,0)!=MENU_ACCEPT){
break;
}else{
if (perm_rootaccess(MSG_U(P_WRITEHOSTS,"write /etc/host.conf"))){
dnsconf_writehostconf (multi,order);
break;
}
}
}
}